/**
 * Main client package
 */
package com.aceitunaproject.gameclient;

import java.util.LinkedList;
import java.util.List;

import javax.swing.JOptionPane;

import com.aceitunaproject.gameclient.AceitunaInterface;
import com.aceitunaproject.shared.exceptions.gamerules.EnumIllegalAction;
import com.aceitunaproject.shared.exceptions.gamerules.IllegalActionException;
import com.aceitunaproject.shared.gamelement.Installation;
import com.aceitunaproject.shared.gamelement.Settlement;
import com.aceitunaproject.shared.gamelement.Unit;
import com.aceitunaproject.shared.map.MapTile;

/**
 * Main controller class for the game client
 * 
 * @author Federico Bergstein
 * 
 */
public class GameClient {

	private AceitunaInterface clientInterface;
	private AceitunaView theView;
	private String username;
	private List<MapTile> mapModel = new LinkedList<MapTile>();

	boolean selectingEnemyUnit = false;
	
	public static void main(String[] args) {

		new GameClient(args[0], args[1]);
	}

	public GameClient(String username, String password) {

		this.username = username;
		theView = new AceitunaView(mapModel, this);
		clientInterface = new AceitunaInterface(username, password, this);

	}

	public void disconnected(boolean gracefully, String reason) {
		theView.displayMessage("disconnected :" + reason);

	}

	public void loggedIn() {
		theView.displayMessage("Logged In as " + username);

	}

	public void mapRefreshed(List<MapTile> areaTiles) {
		mapModel = areaTiles;
		theView.setModel(mapModel);
		theView.refresh();
		theView.nothingSelected();
		if (selectedUnit != null) {
			MapTile unitTile = getTile(selectedUnit.getPositionX(),
					selectedUnit.getPositionY());
			List<Unit> units = unitTile.getUnits();
			boolean notFound = true;
			int i = 0;
			while (notFound && i < units.size()) {
				Unit unit = units.get(i);
				if (unit.getId().equals(selectedUnit.getId())) {
					theView.unitSelected(unit);
					theView.selectTile(unitTile);
					notFound = false;
				}
				i++;
			}

		}

		if (selectedInstallation != null) {
			MapTile installationTile = getTile(selectedInstallation
					.getPositionX(), selectedUnit.getPositionY());
			List<Installation> installations = installationTile
					.getInstallations();
			boolean notFound = true;
			int i = 0;
			while (notFound && i < installations.size()) {
				Installation installation = installations.get(i);
				if (installation.getId().equals(selectedInstallation.getId())) {
					theView.installationSelected(installation);
					theView.selectTile(installationTile);
					notFound = false;
				}
				i++;
			}

		}

		if (selectedSettlement != null) {
			MapTile settlementTile = getTile(selectedSettlement.getPositionX(),
					selectedSettlement.getPositionY());
			if (settlementTile.getSettlement() != null) {
				theView.selectTile(settlementTile);
				theView.settlementSelected(settlementTile.getSettlement());
			}

		}
	}

	private MapTile getTile(int x, int y) {
		for (MapTile tile : mapModel) {
			if (tile.getPosx() == x && tile.getPosy() == y) {
				return tile;
			}
		}
		return null;
	}

	public void ruleViolation(IllegalActionException ruleViolations) {
		String message = "Unable to comply : ";
		for (EnumIllegalAction violation : ruleViolations.getReasons()) {
			message += " " + violation.toString() + "\r\n";
		}
		theView.displayMessage(message);
	}

	public void tileClicked(EnumMouseButton button, MapTile mapTile) {

		switch (button) {
		case RightButton:
			if (selectedUnit != null) {
				selectedUnit.setPositionX(mapTile.getPosx());
				selectedUnit.setPositionY(mapTile.getPosy());
				clientInterface.moveUnit(selectedUnit.getId(), mapTile
						.getPosx(), mapTile.getPosy());
				clientInterface.requestMapRefresh();
			}
			break;

		case LeftButton:

			theView.selectTile(mapTile);

			break;
		default:
			break;
		}

	}

	private Unit selectedUnit;
	private Settlement selectedSettlement;
	private Installation selectedInstallation;

	public void setSelectedUnit(Unit unit) {
		selectedUnit = unit;
		selectedInstallation = null;
		selectedSettlement = null;
	}

	public void setSelectedSettlement(Settlement tileSettlement) {
		selectedUnit = null;
		selectedInstallation = null;
		selectedSettlement = tileSettlement;

	}

	public void setSelectedInstallation(Installation installation) {
		selectedUnit = null;
		selectedInstallation = installation;
		selectedSettlement = null;

	}

	public void orderedToBuildSettlement(Unit theUnit) {
		String name = JOptionPane
				.showInputDialog("Type a name for the new settlement");
		clientInterface.buildSettlement(theUnit, name);
		clientInterface.requestMapRefresh();

	}

	public void orderedToBuildInstallation(Unit theUnit) {
		String name = JOptionPane
				.showInputDialog("Type a name for the new installation");
		clientInterface.buildInstallation(theUnit, name,
				"DefaultInstallationType");
		clientInterface.requestMapRefresh();

	}

	public void orderedToBuildUnit(Settlement theSettlement) {
		String name = JOptionPane
				.showInputDialog("Type a name for the new unit");
		String persons = JOptionPane
				.showInputDialog("Type a number of persons for the new unit");
		clientInterface
				.buildUnit(theSettlement, name, Integer.valueOf(persons));
		clientInterface.requestMapRefresh();

	}

	public void orderedToRefreshMap() {
		clientInterface.requestMapRefresh();

	}

	public void orderedToAttackWithUnit() {
		
		selectingEnemyUnit = true;
		theView.SecondUnitSelection(true);
	}

	public void orderedUnitToAttackUnit(Unit attacker, Unit defender) {
		int confirmresult = JOptionPane.showConfirmDialog(null,"Are you sure?");
		if(confirmresult == 0)
		{
			
			clientInterface.attackUnit(attacker.getId(), defender.getId());
			clientInterface.requestMapRefresh();
		}

	}

	public static void startClient(String username, String password) {
		new GameClient(username, password);

	}

	public void orderedToCancel() {
		theView.SecondUnitSelection(false);
		
	}

	public void secondUnitSelected(Unit unit) {
		if(selectingEnemyUnit)
		{
			selectingEnemyUnit = false;
			theView.SecondUnitSelection(false);
			orderedUnitToAttackUnit(selectedUnit,unit);
		}
	}

}
